package me.android.library.ui;

import android.annotation.SuppressLint;
import android.os.Bundle;

import androidx.fragment.app.FragmentActivity;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;

import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;
import me.android.library.common.service.AbstractService;
import me.android.library.ui.api.LayoutLoader;
import me.android.library.ui.api.Page;
import me.android.library.ui.config.FormInfo;
import me.android.library.ui.config.MenuInfo;
import me.android.library.ui.config.PageInfo;
import me.android.library.ui.config.UiConfig;
import me.android.library.ui.config.UiConfigUtil;
import me.android.library.ui.impl.FormManager;
import mylab.utils.common.StringUtil;

@Slf4j
public class UiService extends AbstractService {

    private static class SingletonHolder {
        @SuppressLint("StaticFieldLeak")
        private static final UiService instance = new UiService();
    }

    public static UiService getInstance() {
        return UiService.SingletonHolder.instance;
    }

    private UiConfig config;
    private Map<String, Page> pageMap;
    private Map<String, FormManager> formMap;
    private String topFormKey;

    private UiService() {

    }

    @Override
    public void init() {
        super.init();

        this.pageMap = Maps.newHashMap();
        this.formMap = Maps.newHashMap();
        this.config = UiConfigUtil.loadFromAsset();
    }

    public FormManager getMain() {
        FormManager fm = getFormManager(config.getMain());
        Preconditions.checkNotNull(fm, "main FormManager is null");
        return fm;
    }

    public FormManager getTop() {
        if (Strings.isNullOrEmpty(topFormKey)) {
            return getMain();
        } else {
            return getFormManager(topFormKey);
        }
    }

    public FormManager getFormManager(String formKey) {
        return formMap.get(formKey);
    }

    public LayoutLoader getLoader() {
        return getTop().getLoader();
    }

    public LayoutLoader getLoader(String formKey) {
        return getFormManager(formKey).getLoader();
    }

    public List<MenuInfo> getMenus() {
        return config.getValidMenus();
    }

    public boolean isMainForm() {
        return Objects.equal(getTop().getFormKey(), config.getMain());
    }

    public boolean isHome() {
        return getTop().isHome();
    }

    public boolean isHomePage(String pageKey) {
        return getTop().isHomePage(pageKey);
    }

    public boolean isCurrentPage(String pageKey) {
        return Objects.equal(getTop().getCurrrentPageKey(), pageKey);
    }

    public void attachActivity(String formKey, FragmentActivity main) {
        attachActivity(formKey, main, null);
    }

    public void attachActivity(String formKey, FragmentActivity main, String pageKey) {
        checkFormKey(formKey);
        FormInfo fi = getFormInfo(formKey);
        if (fi == null) {
            return;
        }

        setTopActivity(formKey);
        FormManager fm = new FormManager(fi);
        formMap.put(formKey, fm);

        fm.attachActivity(main, pageKey);
    }

    public void detachActivity(String formKey) {
        checkFormKey(formKey);
        FormManager fm = getFormManager(formKey);
        if (fm != null) {
            fm.detachActivity();
        } else {
            log.warn("invalid formKey:{}", formKey);
        }
        formMap.remove(formKey);
    }

    public void setTopActivity(String formKey) {
        checkFormKey(formKey);
        topFormKey = formKey;
    }

    public UiService postPage(String pageKey) {
        return postPage(pageKey, null);
    }

    public UiService postPage(String pageKey, Bundle args) {
        getTop().postPage(pageKey, args);
        return this;
    }

    public UiService popBack() {
        getTop().popBack();
        return this;
    }

    public UiService returnHome() {
        getTop().returnHome();
        return this;
    }

    public void toggleMenu() {
        getTop().toggleMenu();
    }

    public Page createPage(String pageKey) {
        PageInfo pi = getPageInfo(pageKey);
        Page page = pi.get();
        Preconditions.checkNotNull(page, "invalid page: " + pageKey);
        pageMap.put(pageKey, page);
        return page;
    }

    public Page getPage(String pageKey) {
        return pageMap.get(pageKey);
    }

    public PageInfo getPageInfo(String pageKey) {
        PageInfo pi = config.getPageInfo(pageKey);
        Preconditions.checkNotNull(pi, "invalid pageKey:" + pageKey);
        return pi;
    }

    public void removePage(String pageKey) {
        pageMap.remove(pageKey);
    }

    private FormInfo getFormInfo(String formKey) {
        checkFormKey(formKey);
        return config.getFormInfo(formKey);
    }

    private void checkFormKey(String formKey) {
        Preconditions.checkState(StringUtil.isNotEmpty(formKey), "pageKey is null or empty");
    }
}
